
const int MAX_ITERATIONS = 15;
const int FADE_DELAY = 10;
const int FADE_STEP = 1;
const int BLUE_PIN = 9;
const int GREEN_PIN = 10;
const int RED_PIN = 11;
const int BUZZER_PIN = 5;
const int IR_PIN = A0;
const int IR_ENABLE_PIN = 4;

boolean colors[3];
int lastColorIndex;
const int BLUE_POS = 0;
const int GREEN_POS = 1;
const int RED_POS = 2;

int iterations = 0;
boolean isPlaying = true;


void setup() 
{
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(IR_PIN, INPUT);
  pinMode(IR_ENABLE_PIN, OUTPUT);
  
  randomSeed(millis());
  resetAllLights();
  
  //Serial.begin(9600);
  music();
  
}

void loop() 
{
  if(!isPlaying)
  {
    iterations = 0;
    digitalWrite(IR_ENABLE_PIN, HIGH);
    isPlaying = checkStart();
    digitalWrite(IR_ENABLE_PIN, LOW);
    
    randomSeed(millis());
    //randomColor();
    
    delay(250);
    resetAllLights();    
    
  }
  else
  {
    digitalWrite(IR_ENABLE_PIN, LOW);
    
    if(iterations>=MAX_ITERATIONS)
    {
      isPlaying=false;
      fadeAllOut();
      resetAllLights();
    }
    else
    {
      int index = lastColorIndex;
      while(index==lastColorIndex)
      {
        index = random(3);        
      }
      lastColorIndex = index;
      
      colors[index] = !colors[index];
      int pin;
      if(index==RED_POS) pin=RED_PIN; 
      else if(index==GREEN_POS) pin=GREEN_PIN;
      else if(index==BLUE_POS) pin=BLUE_PIN;
      else pin=RED_PIN;

/*
      if(colors[RED_POS]) Serial.print("RED ");
      if(colors[GREEN_POS]) Serial.print("GREEN ");
      if(colors[BLUE_POS]) Serial.print("BLUE ");
      Serial.println("");
*/  
      fadeLight(pin, colors[index]);

      iterations++;
    }    
  }
}

boolean checkStart()
{
  int sensor = digitalRead(IR_PIN);
  if(sensor==HIGH)
  {
    //Serial.println("high");
    return false;
  }
  else
  {
    //Serial.println("low");
    return true;  
  }
  
}

void fadeAllOut()
{
    for(int fadeValue = 254 ; fadeValue >= 0; fadeValue -=FADE_STEP) 
    {
      if(colors[RED_POS]) analogWrite(RED_PIN, fadeValue);
      if(colors[GREEN_POS]) analogWrite(GREEN_PIN, fadeValue);
      if(colors[BLUE_POS]) analogWrite(BLUE_PIN, fadeValue);
      delay(FADE_DELAY);
    }  
}

void resetAllLights()
{
  analogWrite(GREEN_PIN, 0);
  analogWrite(BLUE_PIN, 0);
  analogWrite(RED_PIN, 0);
  
  lastColorIndex = GREEN_POS;
  colors[BLUE_POS] = false;
  colors[GREEN_POS] = false;
  colors[RED_POS] = false;
}

void randomColor()
{
  analogWrite(GREEN_PIN, random(255));
  analogWrite(BLUE_PIN, random(255));
  analogWrite(RED_PIN, random(255));
}

void fadeLight(int pin, boolean up)
{
  if(up)
  {
    for(int fadeValue = 0 ; fadeValue <=254; fadeValue +=FADE_STEP)
    {
      analogWrite(pin, fadeValue);
      delay(FADE_DELAY);
    }
  }
  else
  {
    for(int fadeValue = 254 ; fadeValue >= 0; fadeValue -=FADE_STEP) 
    {
      analogWrite(pin, fadeValue);
      delay(FADE_DELAY);
    }
  } 
}

void mtone(unsigned int frequency, unsigned long duration)
{
  randomColor();
  tone(BUZZER_PIN, frequency, duration);
  delay(1+duration); //delay duration should always be 1 ms more than the note in order to separate them.
}

void mpause(unsigned long duration)
{
  delay(1+duration); 
  analogWrite(GREEN_PIN, 0);
  analogWrite(BLUE_PIN, 0);
  analogWrite(RED_PIN, 0);  
}

void music()
{
    // NB: ALL NOTES DEFINED WITH STANDARD ENGLISH NAMES, EXCEPT FROM "A" 
    //THAT IS CALLED WITH THE ITALIAN NAME "LA" BECAUSE A0,A1...ARE THE ANALOG PINS ON ARDUINO.
    // (Ab IS CALLED Ab AND NOT LAb)
    #define	C0 16.35
    #define	Db0	17.32
    #define	D0	18.35
    #define	Eb0	19.45
    #define	E0	20.60
    #define	F0	21.83
    #define	Gb0	23.12
    #define	G0	24.50
    #define	Ab0	25.96
    #define	LA0	27.50
    #define	Bb0	29.14
    #define	B0	30.87
    #define	C1	32.70
    #define	Db1	34.65
    #define	D1	36.71
    #define	Eb1	38.89
    #define	E1	41.20
    #define	F1	43.65
    #define	Gb1	46.25
    #define	G1	49.00
    #define	Ab1	51.91
    #define	LA1	55.00
    #define	Bb1	58.27
    #define	B1	61.74
    #define	C2	65.41
    #define	Db2	69.30
    #define	D2	73.42
    #define	Eb2	77.78
    #define	E2	82.41
    #define	F2	87.31
    #define	Gb2	92.50
    #define	G2	98.00
    #define	Ab2	103.83
    #define	LA2	110.00
    #define	Bb2	116.54
    #define	B2	123.47
    #define	C3	130.81
    #define	Db3	138.59
    #define	D3	146.83
    #define	Eb3	155.56
    #define	E3	164.81
    #define	F3	174.61
    #define	Gb3	185.00
    #define	G3	196.00
    #define	Ab3	207.65
    #define	LA3	220.00
    #define	Bb3	233.08
    #define	B3	246.94
    #define	C4	261.63
    #define	Db4	277.18
    #define	D4	293.66
    #define	Eb4	311.13
    #define	E4	329.63
    #define	F4	349.23
    #define	Gb4	369.99
    #define	G4	392.00
    #define	Ab4	415.30
    #define	LA4	440.00
    #define	Bb4	466.16
    #define	B4	493.88
    #define	C5	523.25
    #define	Db5	554.37
    #define	D5	587.33
    #define	Eb5	622.25
    #define	E5	659.26
    #define	F5	698.46
    #define	Gb5	739.99
    #define	G5	783.99
    #define	Ab5	830.61
    #define	LA5	880.00
    #define	Bb5	932.33
    #define	B5	987.77
    #define	C6	1046.50
    #define	Db6	1108.73
    #define	D6	1174.66
    #define	Eb6	1244.51
    #define	E6	1318.51
    #define	F6	1396.91
    #define	Gb6	1479.98
    #define	G6	1567.98
    #define	Ab6	1661.22
    #define	LA6	1760.00
    #define	Bb6	1864.66
    #define	B6	1975.53
    #define	C7	2093.00
    #define	Db7	2217.46
    #define	D7	2349.32
    #define	Eb7	2489.02
    #define	E7	2637.02
    #define	F7	2793.83
    #define	Gb7	2959.96
    #define	G7	3135.96
    #define	Ab7	3322.44
    #define	LA7	3520.01
    #define	Bb7	3729.31
    #define	B7	3951.07
    #define	C8	4186.01
    #define	Db8	4434.92
    #define	D8	4698.64
    #define	Eb8	4978.03
    // DURATION OF THE NOTES 
    #define BPM 100    //  you can change this value changing all the others
    #define H 2*Q //half 2/4
    #define Q 60000/BPM //quarter 1/4 
    #define E Q/2   //eighth 1/8
    #define S Q/4 // sixteenth 1/16
    #define W 4*Q // whole 4/4
      
  
  
    mtone(C5,E);
    mtone(C5,Q);
    mtone(D5,E);
    mtone(C5,Q);
    mtone(B4,E);
    mtone(B4,E);
    mtone(LA3,Q);
    mtone(LA3,E);
    mpause(E);
/*
    mtone(E3,E);
    mtone(F3,E);
    mtone(G3,E);
    mtone(G4,E);
    mtone(F4,E);
    mtone(B3,Q);
    mtone(LA3,Q);
*/        
  //DO DO RE DO SI SI LA SOL LA SI DO DOSI LA SOL;
  
 
     
}
